#import <Foundation/Foundation.h>
#import <objc/runtime.h>

#import "framework/FWCommon.h"

#import "PIEvent.h"


@implementation PIEvent

@synthesize location, coordinates, sectionTitle, sectionDetails, sectionStartInterval, sectionEndInterval, endDate, allDay, rangeStartDate, rangeEndDate, availability, firstAlarm, nextAlarm, alarms, hasAttendees, attendees, organiser, status, invitation, reminderInteract;


// ******************************************************************************************
#pragma mark -
#pragma mark Initialisation and object management

+ (PIEvent*)nativeEventWithKey:(NSString*)newKey title:(NSString*)newTitle icon:(NSString*)newIcon location:(NSString*)newLocation startDate:(NSDate*)newStart endDate:(NSDate*)newEnd allDay:(BOOL)newAllDay calendar:(NSString*)newCalendar calendarIcon:(NSString*)newCalIcon calendarColor:(UIColor*)newCalColor
{
    PIEvent* event = [[[PIEvent alloc] init] autorelease];
    
    event->key = [newKey copy];
    event->native = YES;
    
    event->title = [newTitle copy];
    event->icon = [newIcon copy];

    if (newLocation && (newLocation.length > 0))
        event->location = [newLocation copy];

    event->allDay = newAllDay;
    [event setStartDate:newStart];
    [event setEndDate:newEnd];

    event->calendar = [newCalendar copy];
    event->calendarIcon = [newCalIcon copy];
    event->calendarColor = [newCalColor retain];

    return event;
}

+ (PIEvent*)piEventWithKey:(NSString*)newKey title:(NSString*)newTitle icon:(NSString*)newIcon location:(NSString*)newLocation startDate:(NSDate*)newStart endDate:(NSDate*)newEnd allDay:(BOOL)newAllDay calendar:(NSString*)newCalendar calendarIcon:(NSString*)newCalIcon calendarColor:(UIColor*)newCalColor
{
    PIEvent* event = [[[PIEvent alloc] init] autorelease];
    
    event->key = [newKey copy];
    event->native = NO;
    
    event->title = [newTitle copy];
    event->icon = [newIcon copy];
    
    if (newLocation && (newLocation.length > 0))
        event->location = [newLocation copy];

    event->allDay = newAllDay;
    [event setStartDate:newStart];
    [event setEndDate:newEnd];
    
    event->calendar = [newCalendar copy];
    event->calendarIcon = [newCalIcon copy];
    event->calendarColor = [newCalColor retain];
    
    return event;
}

- (id)init
{
    self = [super init];
    if (self) {
        coordinatesSet = NO;
        availability = kPICalAvailabilityNotSupported;
        hasAttendees = NO;
        sensitivity = PISensitivityTypeNone;
        
        self.rangeStartDate = [NSDate nullDate];
        self.rangeEndDate = [NSDate nullDate];
        
        self.firstAlarm = [NSDate nullDate];
        self.nextAlarm = [NSDate nullDate];
    }
    
    return self;
}

- (void)dealloc
{
    [location release];
    [coordinates release];
    
    [sectionTitle release];
    [sectionDetails release];

    [endDate release];
    
    [rangeStartDate release];
    [rangeEndDate release];

    [firstAlarm release];
    [nextAlarm release];
    [alarms release];
    
    [organiser release];
    [attendees release];
    
    [super dealloc];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Object duplication

- (id)copyWithZone:(NSZone *)zone
{
    PIEvent* copy = [[[self class] allocWithZone:zone] init];
    
    copy->key = [self.key retain];
    copy->native = self.native;
    
    copy->title = [self.title retain];
    copy->location = [location retain];
    copy->coordinates = [coordinates retain];
    copy->coordinatesSet = coordinatesSet;
    copy->icon = [self.icon retain];
    
    [copy setSectionTitle:sectionTitle];
    
    [copy setStartDate:self.startDate];
    [copy setEndDate:self.endDate];
    copy->allDay = self.allDay;

    [copy setRangeStartDate:self.rangeStartDate];
    [copy setRangeEndDate:self.rangeEndDate];

    copy->calendar = [self.calendar retain];
    copy->calendarIcon = [self.calendarIcon retain];
    copy->calendarColor = [self.calendarColor retain];
    
    copy->availability = self.availability;
    copy->sensitivity = self.sensitivity;
    copy->status = self.status;
    copy->repeating = self.repeating;
    copy->hasAttendees = self.hasAttendees;
    copy->invitation = self.invitation;
    
    [copy setFirstAlarm:self.firstAlarm];
    [copy setNextAlarm:self.nextAlarm];
    [copy setAlarms:self.alarms];

    return copy;
}

- (id)copyWithZone:(NSZone *)zone instance:(NSInteger)instance
{
    PIEvent* copy = [self copyWithZone:zone];
    NSString* newKey = [copy.key stringByAppendingFormat:@"[%d]", instance];
    
    [copy->key release];
    copy->key = [newKey retain];
    
    return copy;
}

- (id)copyInstance:(NSInteger)instance
{
    return [self copyWithZone:NULL instance:instance];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Debugging functions

- (NSString*)shortDescription
{
    return [NSString stringWithFormat:
            @"<%@: %p;"
            " key = %@;"
            " title = %@;"
            " interact = %i;"
            " startDate = %@;"
            " endDate = %@;"
            " firstAlarm = %@;"
            " nextAlarm = %@>",
            [self class],
            self,
            self.key,
            self.title,
            self.reminderInteract,
            self.startDate,
            self.endDate,
            self.firstAlarm,
            self.nextAlarm];
}

- (NSString*)description
{
    return [NSString stringWithFormat:
            @"<%@: %p;"
            " key = %@;"
            " title = %@;"
            " isNative = %@;"
            " icon = %@;"
            " location = %@;"
            " coordinates = %@;"
            " startDate = %@;"
            " endDate = %@;"
            " calendar = %@;"
            " calendarIcon = %@;"
            " calendarColor = %@;"
            " firstAlarm = %@;"
            " nextAlarm = %@;"
            " alarms = %@;"
            " availability = %i;"
            " status = %i;"
            " organiser = %@;"
            " hasAttendees = %@;"
            " attendees = %@;"
            " interact = %i;"
            " isRepeating = %@>",
            [self class],
            self,
            self.key,
            self.title,
            [NSNumber numberWithBool:self.native],
            self.icon,
            location,
            coordinates,
            self.startDate,
            self.endDate,
            self.calendar,
            self.calendarIcon,
            self.calendarColor,
            self.firstAlarm,
            self.nextAlarm,
            self.alarms,
            self.availability,
            self.status,
            self.organiser,
            [NSNumber numberWithBool:self.hasAttendees],
            self.attendees,
            self.reminderInteract,
            [NSNumber numberWithBool:self.repeating]];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Information access

- (void)setLocation:(NSString*)newLocation
{
    if (newLocation && (newLocation.length > 0))
        newLocation = nil;
    
    [newLocation retain];
    [location release];
    location = newLocation;
}

- (NSString*)location
{
    if (!coordinatesSet) {
        coordinatesSet = YES;
        
        // Remove any PI coordinates in the location information
        if (location) {
            if ([location rangeOfString:@"[" options:NSLiteralSearch].location != NSNotFound) {
                NSRange pos = [location rangeOfString:@"\\[-?[0-9]+\\.[0-9]+,-?[0-9]*\\.[0-9]+\\]"
                                              options:NSRegularExpressionSearch];
                if (pos.location != NSNotFound) {
                    NSString* coords = [[location substringWithRange:pos] substringFromIndex:1];
                    coords = [coords substringToIndex:coords.length - 1];

                    NSString* newLocation = [[location substringToIndex:pos.location]
                                             stringByAppendingString:[location substringFromIndex:pos.location + pos.length]];

                    [location release];
                    location = [newLocation retain];
                    coordinates = [coords retain];
                }
            }
        }
    }
    
    return location;
}

- (NSString*)coordinates
{
    if (!coordinatesSet)
        [self location];
    
    return coordinates;
}

- (BOOL)hasDetails
{
    return location && (location.length > 0);
}

@end
